package adoper

import (
	"encoding/json"
	//	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"

	"advertoper/errorcode"
	"advertoper/rpc/client/ip"

	log "github.com/cihub/seelog"
)

//对外的数据请求的接口
//**********************************************添加读锁*****************************
func GetOptionList(req *ReqExtraParam) (uint, []interface{}) { //获取某一位置的数据
	log.Debug("对外的数据请求的接口-GetOptionList")
	data := make([]interface{}, 0)
	MyLock.RLock()
	defer MyLock.RUnlock()

	if _, ok := layouts[req.AppKey]; !ok {
		return errorcode.EC_GL_INVALID_APPKEY, data
	}
	log.Infof("rep.Pos;%s",req.Pos)
	posSeq := layouts[req.AppKey]
	if req.Pos != 0 { //return data in specific position
		if _, ok := posSeq[int(req.Pos)]; !ok {
			return errorcode.EC_ADVERTOPER_POSITION_INVALID, data
		}
		posdata := getSpecificPosData(posSeq[int(req.Pos)], req, int(req.Pos))
		data = append(data, posdata...)
		return errorcode.EC_GL_SUCCESS, data
	}

	for pos, seq := range posSeq {
		posdata := getSpecificPosData(seq, req, pos)
		data = append(data, posdata...)
	}
	return errorcode.EC_GL_SUCCESS, data
}

func getSpecificPosData(seq string, req *ReqExtraParam, pos int) []interface{} {
	log.Infof("sep:%s",seq)
	posdata := make([]interface{}, 0)
	seqArry := strings.Split(seq, ",")
	for _, idstr := range seqArry {
		log.Infof("idstr:%s",idstr)
		id, _ := strconv.Atoi(idstr)
		if _, ok := items[id]; !ok {
			log.Infof("asdadas")
			continue
		}
		if ok := isShow(items[id], req, pos); !ok {
			continue
		} else {
			posdata = append(posdata, items[id])
		}
	}
	return posdata
}

func isShow(item interface{}, req *ReqExtraParam, pos int) bool {
	v := reflect.ValueOf(item)

	itemType := v.Elem().Field(0).Field(1).Int()
	log.Infof("itemType:%s",itemType)
	switch itemType {
	case 1:
		{
			data := item.(*TEXT)
			log.Infof("data:%s",data)
			data.Position = pos
			if ok := isValid(data.Start_tick, data.End_tick); !ok {
				return false
			}
			if ok := isRightVersion(data.versionCode, req.VersionCode); !ok {
				return false
			}
			if ok := isRightArea(data.region, req.ClientIp); !ok {
				return false
			}
			if ok := isRightChannel(data.channel, req.Channel); !ok {
				return false
			}
			return true
		}
	case 2:
		{
			data := item.(*IMG)
			log.Infof("data:%s",data)
			data.Position = pos
			if ok := isValid(data.Start_tick, data.End_tick); !ok {
				return false
			}
			if ok := isRightVersion(data.versionCode, req.VersionCode); !ok {
				return false
			}
			if ok := isRightArea(data.region, req.ClientIp); !ok {
				return false
			}
			if ok := isRightChannel(data.channel, req.Channel); !ok {
				return false
			}
			if data.id == 22 {
				if req.VersionCode < 55 {
					data.Clickable = 0
				} else {
					data.Clickable = 1
				}
			}
			return true
		}
	case 3:
		{
			data := item.(*WEB)
			log.Infof("data:%s",data)
			data.Position = pos
			if ok := isValid(data.Start_tick, data.End_tick); !ok {
				return false
			}
			if ok := isRightVersion(data.versionCode, req.VersionCode); !ok {
				return false
			}
			if ok := isRightArea(data.region, req.ClientIp); !ok {
				return false
			}
			if ok := isRightChannel(data.channel, req.Channel); !ok {
				return false
			}
			return true
		}
	case 4:
		{
			data := item.(*JSON)
			data.Position = pos
			if ok := isValid(data.Start_tick, data.End_tick); !ok {
				return false
			}
			if ok := isRightVersion(data.versionCode, req.VersionCode); !ok {
				return false
			}
			if ok := isRightArea(data.region, req.ClientIp); !ok {
				return false
			}
			if ok := isRightChannel(data.channel, req.Channel); !ok {
				return false
			}
			return true
		}
	default:
		{
			return false
		}
	}
	return false
}

func getBaseInfo(dt map[string]interface{}, base *BASE) {
	base.id = int(dt["id"].(int64))
	//base.Position = dt["position"].(int64)
	base.versionCode = string(dt["version_code"].([]byte))
	base.region = string(dt["region"].([]byte))
	base.channel = string(dt["channel"].([]byte))
	base.ItemType = dt["type"].(int64)
	base.Start_tick = dt["start_tick"].(int64)
	base.End_tick = dt["end_tick"].(int64)
	base.Weight = dt["weight"].(int64)
}

func getClickInfo(dt map[string]interface{}, click *CLICK) bool {
	click.Clickable = dt["clickable"].(int64)
	click.Action = dt["action"].(int64)
	click.Args = make(map[string]interface{})
	args := dt["args"].([]byte)
	err := json.Unmarshal(args, &(click.Args))
	if err != nil {
		log.Debugf("getClickInfo json err, %s, id:%d", err.Error(), dt["id"].(int64))
		return false
	}
	return true
}

//获取文字信息
func getText(dt map[string]interface{}) *TEXT {
	cd := &TEXT{}
	getBaseInfo(dt, &cd.BASE)
	if ok := getClickInfo(dt, &cd.CLICK); !ok {
		return nil
	}
	cd.Content = string(dt["content"].([]byte))
	cd.Color = dt["color"].(int64)
	cd.Router = string(dt["router"].([]byte))
	return cd
}

//获取图片信息
func getImg(dt map[string]interface{}) *IMG {
	cd := &IMG{}
	getBaseInfo(dt, &cd.BASE)
	if ok := getClickInfo(dt, &cd.CLICK); !ok {
		return &IMG{tag: -1}
		//return nil
	}

	cd.Urls = make([]*URL, 0)
	pic := dt["pic"].([]byte)
	cd.Router = string(dt["router"].([]byte))
	err := json.Unmarshal(pic, &(cd.Urls))
	if err != nil {
		log.Debugf("getImg json err, %s, id:%d", err.Error(), dt["id"].(int64))
		return &IMG{tag: -1}
		//return nil
	}

	return cd
}

//获取WEB信息
func getWeb(dt map[string]interface{}) *WEB {
	cd := &WEB{}
	getBaseInfo(dt, &cd.BASE)

	cd.Url = string(dt["web_url"].([]byte))
	cd.Router = string(dt["router"].([]byte))

	return cd
}

//获取JSON信息
func getJson(dt map[string]interface{}) *JSON {
	var f interface{}
	cd := &JSON{}
	//cd.Position = dt["position"].(int64)
	getBaseInfo(dt, &cd.BASE)
	b := dt["content"].([]byte)
	json.Unmarshal(b, &f)
	cd.Data = f.(map[string]interface{})

	return cd
}

func isValid(start, end int64) bool {
	tm := time.Now().Unix()
	if end <= tm {
		return false
	}
	if start > tm {
		return false
	}
	return true
}

func isRightVersion(reqVersion string, paramVersion int) bool {
	if reqVersion == ALL_VERSION {
		return true
	}
	vcstr := strings.Split(reqVersion, SEP)
	compareWay := vcstr[0]
	vc, _ := strconv.Atoi(vcstr[1])
	switch compareWay {
	case "=":
		{
			return (paramVersion == vc)
		}
	case ">":
		{
			return (paramVersion > vc)
		}
	case "<":
		{
			return (paramVersion < vc)
		}
	default:
	}
	return true
}

func isRightArea(reqArea, clientIp string) bool {
	if reqArea == ALL_AREA {
		return true
	}
	areaArry := strings.Split(reqArea, SEP)
	ipdata := ip.IPLocation(clientIp)
	if ipdata == nil || len(ipdata.RegionCode) < 4 {
		return false
	}
	switch areaArry[0] {
	case "contain":
		{
			return strings.Contains(areaArry[1], ipdata.RegionCode[0:4])
		}
	case "!contain":
		{
			return !strings.Contains(areaArry[1], ipdata.RegionCode[0:4])
		}
	default:
		{
			return false
		}
	}
	/*if ipdata != nil && len(ipdata.RegionCode) >= 4 && strings.Contain(reqArea, ipdata.RegionCode[0:4]) {
		return true
	}*/
	return false
}

func isRightChannel(reqChannel, paramChannel string) bool {
	if reqChannel == ALL_CHANNEL {
		return true
	}
	channelArry := strings.Split(reqChannel, SEP)
	switch channelArry[0] {
	case "contain":
		{
			return strings.Contains(channelArry[1], paramChannel)
		}
	case "!contain":
		{
			return !strings.Contains(channelArry[1], paramChannel)
		}
	default:
		{
			return false
		}
	}
	return false
}

type IPQueryRespItem struct {
	Msg      string `json:"msg"`
	Province string `json:"province"`
	City     string `json:"city"`
	County   string `json:"county"`
}
